﻿namespace TNet
{
    using System;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public static class UnityTools
    {
        public static void Broadcast(string methodName, params object[] parameters)
        {
            MonoBehaviour[] behaviourArray = UnityEngine.Object.FindObjectsOfType(typeof(MonoBehaviour)) as MonoBehaviour[];
            int index = 0;
            int length = behaviourArray.Length;
            while (index < length)
            {
                MonoBehaviour behaviour = behaviourArray[index];
                MethodInfo method = behaviour.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                if (method != null)
                {
                    try
                    {
                        method.Invoke(behaviour, parameters);
                    }
                    catch (Exception exception)
                    {
                        Debug.LogError(string.Concat(new object[] { exception.InnerException.Message, " (", behaviour.GetType(), ".", methodName, ")\n", exception.InnerException.StackTrace, "\n" }), behaviour);
                    }
                }
                index++;
            }
        }

        public static void Clear(object[] objs)
        {
            int index = 0;
            int length = objs.Length;
            while (index < length)
            {
                objs[index] = null;
                index++;
            }
        }

        public static bool ExecuteAll(List<CachedFunc> rfcs, byte funcID, params object[] parameters)
        {
            for (int i = 0; i < rfcs.size; i++)
            {
                CachedFunc ent = rfcs[i];
                if (ent.id == funcID)
                {
                    if (ent.parameters == null)
                    {
                        ent.parameters = ent.func.GetParameters();
                    }
                    try
                    {
                        if ((ent.parameters.Length == 1) && (ent.parameters[0].ParameterType == typeof(object[])))
                        {
                            object[] objArray1 = new object[] { parameters };
                            ent.func.Invoke(ent.obj, objArray1);
                        }
                        else
                        {
                            ent.func.Invoke(ent.obj, parameters);
                        }
                        return true;
                    }
                    catch (Exception exception)
                    {
                        PrintException(exception, ent, funcID, string.Empty, parameters);
                        return false;
                    }
                }
            }
            return false;
        }

        public static bool ExecuteAll(List<CachedFunc> rfcs, string funcName, params object[] parameters)
        {
            bool flag = false;
            for (int i = 0; i < rfcs.size; i++)
            {
                CachedFunc ent = rfcs[i];
                if (ent.func.Name == funcName)
                {
                    flag = true;
                    if (ent.parameters == null)
                    {
                        ent.parameters = ent.func.GetParameters();
                    }
                    try
                    {
                        if ((ent.parameters.Length == 1) && (ent.parameters[0].ParameterType == typeof(object[])))
                        {
                            object[] objArray1 = new object[] { parameters };
                            ent.func.Invoke(ent.obj, objArray1);
                        }
                        else
                        {
                            ent.func.Invoke(ent.obj, parameters);
                        }
                        return true;
                    }
                    catch (Exception exception)
                    {
                        PrintException(exception, ent, 0, funcName, parameters);
                    }
                }
            }
            return flag;
        }

        public static bool ExecuteFirst(List<CachedFunc> rfcs, byte funcID, out object retVal, params object[] parameters)
        {
            retVal = null;
            for (int i = 0; i < rfcs.size; i++)
            {
                CachedFunc ent = rfcs[i];
                if (ent.id == funcID)
                {
                    if (ent.parameters == null)
                    {
                        ent.parameters = ent.func.GetParameters();
                    }
                    try
                    {
                        retVal = ((ent.parameters.Length != 1) || (ent.parameters[0].ParameterType != typeof(object[]))) ? ent.func.Invoke(ent.obj, parameters) : ent.func.Invoke(ent.obj, new object[] { parameters });
                        return (retVal != null);
                    }
                    catch (Exception exception)
                    {
                        PrintException(exception, ent, funcID, string.Empty, parameters);
                        return false;
                    }
                }
            }
            return false;
        }

        public static GameObject Instantiate(GameObject go, Vector3 pos, Quaternion rot, Vector3 velocity, Vector3 angularVelocity)
        {
            if (go != null)
            {
                go = UnityEngine.Object.Instantiate(go, pos, rot) as GameObject;
                Rigidbody component = go.GetComponent<Rigidbody>();
                if (component == null)
                {
                    return go;
                }
                if (component.isKinematic)
                {
                    component.isKinematic = false;
                    component.velocity = velocity;
                    component.angularVelocity = angularVelocity;
                    component.isKinematic = true;
                    return go;
                }
                component.velocity = velocity;
                component.angularVelocity = angularVelocity;
            }
            return go;
        }

        public static bool IsParentChild(GameObject parent, GameObject child)
        {
            return (((parent != null) && (child != null)) && IsParentChild(parent.transform, child.transform));
        }

        public static bool IsParentChild(Transform parent, Transform child)
        {
            if ((parent != null) && (child != null))
            {
                while (child != null)
                {
                    if (parent == child)
                    {
                        return true;
                    }
                    child = child.parent;
                }
            }
            return false;
        }

        public static Rect PadRect(Rect rect, float padding)
        {
            Rect rect2 = rect;
            rect2.xMin -= padding;
            rect2.xMax += padding;
            rect2.yMin -= padding;
            rect2.yMax += padding;
            return rect2;
        }

        private static void PrintException(Exception ex, CachedFunc ent, int funcID, string funcName, params object[] parameters)
        {
            string str4;
            string str = string.Empty;
            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    if (i != 0)
                    {
                        str = str + ", ";
                    }
                    str = str + parameters[i].GetType().ToString();
                }
            }
            string str2 = string.Empty;
            if (ent.parameters != null)
            {
                for (int j = 0; j < ent.parameters.Length; j++)
                {
                    if (j != 0)
                    {
                        str2 = str2 + ", ";
                    }
                    str2 = str2 + ent.parameters[j].ParameterType.ToString();
                }
            }
            string message = "[TNet] Failed to call RFC ";
            if (string.IsNullOrEmpty(funcName))
            {
                str4 = message;
                object[] objArray1 = new object[] { str4, "#", funcID, " on ", (ent.obj == null) ? "<null>" : ent.obj.GetType().ToString() };
                message = string.Concat(objArray1);
            }
            else
            {
                str4 = message;
                object[] objArray2 = new object[] { str4, ent.obj.GetType(), ".", funcName };
                message = string.Concat(objArray2);
            }
            if (ex.InnerException != null)
            {
                message = message + ": " + ex.InnerException.Message + "\n";
            }
            else
            {
                message = message + ": " + ex.Message + "\n";
            }
            if (str != str2)
            {
                message = (message + "  Expected args: " + str2 + "\n") + "  Received args: " + str + "\n\n";
            }
            if (ex.InnerException != null)
            {
                message = message + ex.InnerException.StackTrace + "\n";
            }
            else
            {
                message = message + ex.StackTrace + "\n";
            }
            Debug.LogError(message);
        }

        public static float SpringLerp(float from, float to, float strength, float deltaTime)
        {
            if (deltaTime > 1f)
            {
                deltaTime = 1f;
            }
            int num = Mathf.RoundToInt(deltaTime * 1000f);
            deltaTime = 0.001f * strength;
            for (int i = 0; i < num; i++)
            {
                from = Mathf.Lerp(from, to, deltaTime);
            }
            return from;
        }
    }
}

